<!--
 * @Description: 
 * @Author: chenjiaxin
 * @Date: 2022-02-03 09:25:27
 * @LastEditTime: 2022-02-17 10:24:07
 * @FilePath: \super-unit\test\index.html
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>测试</title>
  </head>
  <body>
    <!-- <script
      src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"
      referrerpolicy="no-referrer"
    ></script> -->
    <!-- <script src="../lib/utils/index.js" type="module"></script> -->
    <script>
      let optoString = Object.prototype.toString;
      // let set = new Set([1,2,2,3]);

      // let set_c = _.cloneDeep(set);
      // set_c.add(100);

      // iteratorObj = set[Symbol.iterator]();

      // let arr = [1,2,3,3];
      // iteratorArr = arr[Symbol.iterator]();

      // console.log(set, set_c, optoString.call(iteratorObj), optoString.call(iteratorArr));

      // // console.log(_.cloneDeep(new Date()));

      // let date = new Date();
      // console.log(date[Symbol.iterator]);
      /**
       * ===>>> 使用map 是为了解决循环引用的问题
       */
      const cloneDeepObj = (target, map = new WeakMap()) => {
        let temp;
        if (target && typeof target === "object") {
          //Object Array 以及通过new 构造函数都是 object
          if (map.has(target)) {
            return map.get(target);
          }
          temp = Array.isArray(target) ? [] : {};
          debugger;
          map.set(target, temp);
          // console.log(map, target, temp);
          console.log(temp);
          for (const key in target) {
            // if (target === target[key]) {
            //  // ===>>> 如果是子级的子级循环引用了 就不行了比如：obj.user.info = obj 就不行了
            //   // let newObj = {}
            //   // temp[key] = target;
            // } else {
            //   temp[key] = cloneDeepObj(target[key], map);
            // }
            temp[key] = cloneDeepObj(target[key], map);
          }
        } else {
          // string undefined boolean number null symbol function
          temp = target;
        }
        return temp;
      };

      let obj = {
        nu: null,
        undef: undefined,
        name: "cjx",
        age: 18,
        friends: ["why", "coder"],
        user: {
          address: "深圳"
        },
        sy: Symbol("AA"),
        fn: function () {
          console.log(this.name, "===");
        },
        set: new Set([{ id: 1, name: "cjx" }])
      };
      obj.info = obj;

      const cloneDeep = (target) => {
        let temp; //存储新数据
        if (target && typeof target === "object") {
          //Object Array 以及通过new 构造函数都是 object
          //判断是否是 可迭代对象。注：object对象 不是可迭代对象
          let iteratorObj = target[Symbol.iterator] && target[Symbol.iterator]();
          if (iteratorObj) {
            // 是可迭代对象
            let target_types = optoString.call(iteratorObj).replace(/\[|]/g, "").split(" "); // "object Array Iterator"
            let valueType = target_types[1];
            temp = createIterableValue(valueType);
            // console.log("===", valueType, temp);
            for (const iterator of target) {
              if (valueType === "Set" || valueType === "Map" || valueType === "WeakSet" || valueType === "WeakMap") {
                temp.add(cloneDeep(iterator));
                // console.log(temp);S
              } else {
                temp.push(cloneDeep(iterator));
              }
            }
          } else {
            //不是可迭代对象 这里有object。
            temp = {}; //如果是Proxy对象 把它转成了普通的object对象
            for (const key in target) {
              // if (Object.hasOwnProperty.call(object, key)) {
              temp[key] = cloneDeep(target[key]);

              // }
            }
          }
        } else {
          // string undefined boolean number null symbol function  bigint
          temp = target;
        }
        return temp;
      };
      function createIterableValue(value) {
        let n;
        switch (value) {
          case "Array":
            n = [];
            break;
          case "Set":
            n = new Set();
            break;
          case "Map":
            n = new Map();
            break;
          case "WeakSet":
            n = new WeakSet();
            break;
          case "WeakMap":
            n = new WeakMap();
            break;
          default:
            break;
        }
        return n;
      }
      //拷贝
      let obj_clone = cloneDeepObj(obj);
      // let obj_clone = cloneDeep(obj);

      //修改拷贝的数据
      obj_clone.name = "chen";
      obj_clone.user.address = "北京";

      for (const iterator of obj.set) {
        iterator.name = "AAA";
      }

      console.log(obj, obj_clone);
    </script>
  </body>
</html>
